package com.lagou.edu.factory;

import com.lagou.edu.pojo.BeanDefinition;
import org.dom4j.Element;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * @ClassName AbstractBeanFactory
 * @Description TODO
 * @Auth ying.xiao
 * @Date 2021/2/7
 * @Version 1.0.0
 */
public class AbstractBeanFactory extends BeanFactory{

    public static void doCreateBean() throws Exception {
        for (BeanDefinition beanDefinition : list) {
            Object o = doCreateBean(beanDefinition);
            map.put(beanDefinition.getId(),o);
        }

    }

    /**
     * 单个beanDefinantiao 进行是实例化流程
     * @param beanDefinition
     * @return
     * @throws Exception
     */
    private static Object doCreateBean(BeanDefinition beanDefinition) throws Exception {
        //实例化bean
        Object instance = instanceBean(beanDefinition);

        //设置参数属性
        populateBean(beanDefinition,instance);
        //后置处理
        Object proxyInstance = initializeBean(beanDefinition, instance);

        return proxyInstance;
    }

    /**
     *  实例化bean,未设置参数，此时是一个未完整得bean
     * @param beanDefinition
     * @return
     * @throws Exception
     */
    private static Object instanceBean(BeanDefinition beanDefinition) throws Exception {
        Class<?> aClass = Class.forName(beanDefinition.getBeanClass());
        Object o = aClass.newInstance();  // 实例化之后的对象
        return o;
    }

    /**
     *  对bean进行后置得代理，对事务操作以代理得方式进行
     * @param instance
     */
    private static Object initializeBean(BeanDefinition beanDefinition,Object instance) throws Exception {
        ProxyFactory proxyFactory = ProxyFactory.class.newInstance();
        Object jdkProxy = proxyFactory.getCglibProxy(instance);
        mapProxy.put(beanDefinition.getId(),jdkProxy);
        return instance;
    }

    /**
     *   设置bean属性，并对依赖进行实例化
     * @param beanDefinition
     * @param instance
     * @throws Exception
     */
    private static void populateBean(BeanDefinition beanDefinition, Object instance) throws Exception {
        Map<String, String> propertys = beanDefinition.getPropertys();
        Class<?> aClass = instance.getClass();
        // 解析property，获取父元素
        for (Map.Entry entry : propertys.entrySet()) {
            String ref = (String) entry.getValue();
            BeanDefinition beanDefinitionRef = list.stream().filter(p -> p.getId().equals(ref)).findFirst().get();
            Field declaredField = aClass.getDeclaredField(ref);
            declaredField.setAccessible(true);
            Object value = map.get(beanDefinitionRef.getId());
            if(null != value){
                declaredField.set(instance,value);
            }else{
                Object o = doCreateBean(beanDefinitionRef);
                declaredField.set(instance,o);
            }
        }
    }
}
